package com.iussoft.receiveData.redis;

import com.apache.tools.StrUtil;
import com.iussoft.es.config.EsClientFactory;
import com.iussoft.es.entity.EsMap;
import com.iussoft.es.entity.Field;
import com.iussoft.es.entity.Page;
import com.iussoft.es.service.ElasticsearchServiceImpl;
import io.searchbox.client.JestClient;
import io.searchbox.core.SearchResult;
import io.searchbox.core.search.aggregation.DateHistogramAggregation;
import io.searchbox.core.search.aggregation.MaxAggregation;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.TermsAggregation;
import net.sf.json.JSONObject;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @description: ES查询实现
 * @author: Hou Dayu
 * @date: Created in 2020/5/6
 */
@Service("searchEsService")
public class SearchEsServiceImpl extends ElasticsearchServiceImpl {

    @Override
    public Page pageList(String indexName, String infoType, int pageIndex, int pageSize, List<Field> fields, List<Field> fieldForOrs, String dataStatus, SortBuilder sortBuilder) {
        pageIndex = (pageIndex == 0) ? 1 : pageIndex;
        pageSize = (pageSize == 0) ? 5 : pageSize;
        Page page = new Page();
        page.setPageNeeded(pageIndex);
        page.setPageSize(pageSize);
        JSONObject queryJson = this.getQueryBuilderStr(fields, fieldForOrs);
        if (queryJson.isEmpty()) {
            page.setErrorCode(302);
            page.setMessage("缺失查询参数");
            return page;
        }
        int from = (pageIndex - 1) * pageSize;//设置起始页
        JSONObject json = new JSONObject();
        json.put("from", from);
        json.put("size", pageSize);
        json.put("query", queryJson);
        if (null != sortBuilder) {//排序设置
            json.put("sort", sortBuilder.toString());
        }
        JestClient jestClient = null;
        if(infoType.equalsIgnoreCase("log")){
            jestClient = EsClientFactory.getJestClient();
        }
        if(null == jestClient){
            jestClient = EsClientFactory.defClient();
        }
        SearchResult searchResult = this.execute(jestClient,"pageList", indexName,"doc",json.toString(),"");
        if (searchResult == null || !searchResult.isSucceeded()) {
            page.setErrorCode(302);
            if(null == searchResult){
                page.setMessage("ES查询失败");
            }else {
                page.setMessage(searchResult.getErrorMessage());
            }
            return page;
        }
        Long count = searchResult.getTotal();
        if (count == 0) {
            return page;
        }
        List hits = searchResult.getHits(EsMap.class);
        int pageCount = (int) Math.ceil(count/pageSize);
        page.setPageCount(pageCount);
        page.setCount(count.intValue());
        List list = new ArrayList();
        for (int i = 0; i < hits.size(); i++) {
            SearchResult.Hit<EsMap, Void> hit = (SearchResult.Hit<EsMap, Void>) hits.get(i);
            list.add(hit.source);
        }
        page.setPageObjects(list);
        return page;
    }

    /**
     * 按条件查询（统计用）
     */
    public Object searchByQuery(String indexName,String infoType, JSONObject query){
        JestClient jestClient = null;
        if(infoType.equalsIgnoreCase("log")){
            jestClient = EsClientFactory.getJestClient();
        }
        if(null == jestClient){
            jestClient = EsClientFactory.defClient();
        }
        SearchResult searchResult = this.execute(jestClient,"searchByQuery", indexName,"doc",query.toString(),"");
        if (searchResult == null || !searchResult.isSucceeded()) {
            return null;
        }
        Long count = searchResult.getTotal();
        if (count == 0) {
            return null;
        }
        MetricAggregation ma = searchResult.getAggregations();
        JSONObject aggs = query.getJSONObject("aggs");
        if(aggs == null || aggs.size()==0){
            return searchResult.getTotal();
        }
        Iterator<String> it = aggs.keys();
        String key = null;
        while(it.hasNext()){
            key = it.next();
            break;
        }
        try {
            DateHistogramAggregation dd = ma.getDateHistogramAggregation(key);
            List<DateHistogramAggregation.DateHistogram> list = dd.getBuckets();
            List<Object> data = new ArrayList();
            for (DateHistogramAggregation.DateHistogram dh : list) {
                JSONObject dataObj = JSONObject.fromObject(dh);
                MaxAggregation max = dh.getMaxAggregation("1");
                if (!StrUtil.isEmpty(max)) {
                    dataObj.put("value", max.getMax());
                }
                TermsAggregation terms = dh.getTermsAggregation("3");
                if (null != terms) {
                    dataObj.put("value", terms.getBuckets());
                }
                data.add(dataObj);
            }
            return data;
        } catch (Exception e){
            TermsAggregation value = ma.getTermsAggregation(key);
            return value.getBuckets();
        }
    }

    public Map<String,Object> pageList(String indexName, String infoType, String queryStr){
        JestClient jestClient = null;
        if(infoType.equalsIgnoreCase("log")){
            jestClient = EsClientFactory.getJestClient();
        }
        if(null == jestClient){
            jestClient = EsClientFactory.defClient();
        }
        List list = new ArrayList();
        Map<String,Object> data = new HashMap();
        SearchResult searchResult = this.execute(jestClient,"pageList", indexName,"doc",queryStr,"");
        if (searchResult == null || !searchResult.isSucceeded() || searchResult.getTotal()==0) {
            data.put("total","0");
            data.put("rows",list);
            return data;
        }
        List hits = searchResult.getHits(EsMap.class);
        for (int i = 0; i < hits.size(); i++) {
            SearchResult.Hit<EsMap, Void> hit = (SearchResult.Hit<EsMap, Void>) hits.get(i);
            list.add(hit.source);
        }
        data.put("total",searchResult.getTotal());
        data.put("rows",list);
        return data;
    }
}
